# encoding: utf-8
# @File  : results_manager.py
# @Author: shaoyun
# @Date  :  2025/06/03

from datetime import datetime
from typing import Dict, Any, Optional, List

from loguru import logger

from app.db.mongo_manager import MongoDB
from app.models.spider_result import SpiderResult


class ResultsManager:
    """爬虫结果管理器"""

    def __init__(self):
        self.collection = "spider_results"

    async def save_result(self, result: SpiderResult) -> bool:
        """保存爬虫结果"""
        try:
            data = result.model_dump()
            await MongoDB.insert_one(self.collection, data)
            logger.info(f"Saved result for task {result.task_id}")
            return True
        except Exception as e:
            logger.error(f"Error saving spider result: {e}")
            return False

    async def get_result(self, task_id: str) -> Optional[SpiderResult]:
        """获取指定任务的爬虫结果"""
        try:
            result = await MongoDB.find_one(self.collection, {"task_id": task_id})
            if result:
                # 移除MongoDB的_id字段
                if "_id" in result:
                    del result["_id"]
                return SpiderResult(**result)
            return None
        except Exception as e:
            logger.error(f"Error getting spider result: {e}")
            return None

    async def update_result(self, task_id: str, data: Dict[str, Any]) -> bool:
        """更新爬虫结果"""
        try:
            data["updated_at"] = datetime.utcnow()
            modified_count = await MongoDB.update_one(
                self.collection,
                {"task_id": task_id},
                data
            )
            return modified_count > 0
        except Exception as e:
            logger.error(f"Error updating spider result: {e}")
            return False

    async def delete_result(self, task_id: str) -> bool:
        """删除爬虫结果"""
        try:
            deleted_count = await MongoDB.delete_one(self.collection, {"task_id": task_id})
            return deleted_count > 0
        except Exception as e:
            logger.error(f"Error deleting spider result: {e}")
            return False

    async def get_results_by_spider(
            self,
            spider_id: str,
            limit: int = 10,
            skip: int = 0
    ) -> List[SpiderResult]:
        """获取指定爬虫的所有结果"""
        try:
            results = await MongoDB.find_many(
                self.collection,
                {"spider_id": spider_id},
                skip=skip,
                limit=limit
            )

            spider_results = []
            for doc in results:
                if "_id" in doc:
                    del doc["_id"]
                spider_results.append(SpiderResult(**doc))

            return spider_results
        except Exception as e:
            logger.error(f"Error getting spider results: {e}")
            return []

    async def get_latest_results(self, limit: int = 10) -> List[SpiderResult]:
        """获取最新的爬虫结果"""
        try:
            # MongoDB的find_many需要扩展以支持排序
            db = await MongoDB.get_database()
            cursor = db[self.collection].find().sort("created_at", -1).limit(limit)

            results = []
            async for doc in cursor:
                if "_id" in doc:
                    del doc["_id"]
                results.append(SpiderResult(**doc))

            return results
        except Exception as e:
            logger.error(f"Error getting latest results: {e}")
            return []

    async def get_results_stats(self, spider_id: Optional[str] = None) -> Dict[str, Any]:
        """获取结果统计信息"""
        try:
            match_filter = {"spider_id": spider_id} if spider_id else {}

            pipeline = [
                {"$match": match_filter},
                {
                    "$group": {
                        "_id": "$success",
                        "count": {"$sum": 1}
                    }
                }
            ]

            stats = await MongoDB.aggregate(self.collection, pipeline)

            total = 0
            success_count = 0
            failed_count = 0

            for stat in stats:
                if stat["_id"] is True:
                    success_count = stat["count"]
                else:
                    failed_count = stat["count"]
                total += stat["count"]

            return {
                "total": total,
                "success": success_count,
                "failed": failed_count,
                "success_rate": (success_count / total * 100) if total > 0 else 0
            }
        except Exception as e:
            logger.error(f"Error getting results stats: {e}")
            return {
                "total": 0,
                "success": 0,
                "failed": 0,
                "success_rate": 0
            }

    async def cleanup_old_results(self, days: int = 30) -> int:
        """清理旧的结果数据"""
        try:
            from datetime import timedelta
            cutoff_date = datetime.utcnow() - timedelta(days=days)

            db = await MongoDB.get_database()
            result = await db[self.collection].delete_many({
                "created_at": {"$lt": cutoff_date}
            })

            logger.info(f"Cleaned up {result.deleted_count} old results")
            return result.deleted_count
        except Exception as e:
            logger.error(f"Error cleaning up old results: {e}")
            return 0


# 创建全局实例
results_manager = ResultsManager()